package sound;

import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.control.VolumeControl;


/**
 * The Class SoundGenerator is responsible for loading 
 * and playing sounds and for volume regulation.
 */
public class SoundGenerator {
	
	/** The Player for the background-Loopsound. */
	private Player bgLoop;
	
	private Player seagull1;
	private Player seagull2;
	private Player horn;
//	private Player splash;
	private Player flash;
	
	private float seagullTimer = 0.0f;
	private float hornTimer = 0.0f;
	
	private Random random;
	
	private boolean muted = false;
	
	/**
	 * Instantiates a new sound generator and loads all sounds.
	 */
	public SoundGenerator() {
		loadSounds();
		random = new Random();
	}
	
	/**
	 * Calculates if a seagull-sound should played.
	 * Plays seagull-sounds in partly randomized intervalls.
	 *
	 * @param time the passed time
	 */
	public void updateSeagulls(float time) {
		while (seagullTimer < .0f) { // create Seagullsound

			playSeagull();
			
			seagullTimer += (float)Math.abs(random.nextInt() % 1000); // restart timer
		}
		
		seagullTimer -= time;
	}
	
	/**
	 * Calculates if a horn-sound should played.
	 * Plays horn-sounds in partly randomized intervalls.
	 *
	 * @param time the passed time
	 */
	public void updateHorn(float time) {
		while (hornTimer < .0f) { // create Seagullsound

			playHorn();
			
			hornTimer += (float)Math.abs(random.nextInt() % 1000); // restart timer
		}
		
		hornTimer -= time;
	}
	
	/**
	 * Pause all active sounds.
	 */
	public void pauseSounds() {
		try {
			if(bgLoop.getState() == Player.STARTED)
				bgLoop.stop();
			if(seagull1.getState() == Player.STARTED)
				seagull1.stop();
			if(seagull2.getState() == Player.STARTED)
				seagull2.stop();
			if(horn.getState() == Player.STARTED)
				horn.stop();
//			if(splash.getState() == Player.STARTED)
//				splash.stop();
			if(flash.getState() == Player.STARTED)
				flash.stop();
		} catch (MediaException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Continue all paused sounds.
	 */
	public void continueSounds() {
		try {
			bgLoop.start();
			if(seagull1.getMediaTime() > 0)
				seagull1.start();
			if(seagull2.getMediaTime() > 0)
				seagull2.start();
			if(horn.getMediaTime() > 0)
				horn.start();
//			if(splash.getMediaTime() > 0)
//				splash.start();
			if(flash.getMediaTime() > 0)
				flash.start();
		} catch (MediaException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Changes the actual mute state.
	 */
	public void changeMuteState() {
		if(muted)
			this.unmute();
		else
			this.mute();
		
		muted = ! muted;
	}
	
	/**
	 * Mutes all Players.
	 */
	private void mute() {
		((VolumeControl)bgLoop.getControl("VolumeControl")).setMute(true);
		((VolumeControl)seagull1.getControl("VolumeControl")).setMute(true);
		((VolumeControl)seagull2.getControl("VolumeControl")).setMute(true);
		((VolumeControl)horn.getControl("VolumeControl")).setMute(true);
//		((VolumeControl)splash.getControl("VolumeControl")).setMute(true);
		((VolumeControl)flash.getControl("VolumeControl")).setMute(true);
	}
	
	/**
	 * Unmutes all Players.
	 */
	private void unmute()  {
		((VolumeControl)bgLoop.getControl("VolumeControl")).setMute(false);
		((VolumeControl)seagull1.getControl("VolumeControl")).setMute(false);
		((VolumeControl)seagull2.getControl("VolumeControl")).setMute(false);
		((VolumeControl)horn.getControl("VolumeControl")).setMute(false);
//		((VolumeControl)splash.getControl("VolumeControl")).setMute(false);
		((VolumeControl)flash.getControl("VolumeControl")).setMute(false);
		
	}
	
	/**
	 * Plays a splash-sound.
	 */
	public void playSplash() {
//		try {
//			splash.start();
//		} catch (MediaException e) {
//			e.printStackTrace();
//		}
	}
	
	/**
	 * Plays a horn-sound.
	 */
	public void playHorn() {
		if(horn.getState() != Player.STARTED) {
			try {
				horn.start();
			} catch (MediaException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Plays a seagull-sound randomly choosen out of two.
	 */
	public void playSeagull() {
		if(random.nextInt()%2 == 0) {
			if(seagull1.getState() != Player.STARTED) {
				try {
					seagull1.start();
				} catch (MediaException e) {
					e.printStackTrace();
				}
			}
			else if(seagull2.getState() != Player.STARTED) {
				try {
					seagull2.start();
				} catch (MediaException e) {
					e.printStackTrace();
				}
			}
		}
		else {
			if(seagull2.getState() != Player.STARTED) {
				try {
					seagull2.start();
				} catch (MediaException e) {
					e.printStackTrace();
				}
			}
			else if(seagull1.getState() != Player.STARTED) {
				try {
					seagull1.start();
				} catch (MediaException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * Plays a flash sound.
	 */
	public void playFlashSound() {
		if(flash.getState() != Player.STARTED) {
			try {
				flash.start();
			} catch (MediaException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Loads all sounds used.
	 */
	private void loadSounds() {
		try {
			InputStream is;
			is = getClass().getResourceAsStream("/sounds/wavesloop.mp3");
			bgLoop = Manager.createPlayer(is, "audio/mpeg");

			is = getClass().getResourceAsStream("/sounds/seagull1.mp3");
			seagull1 = Manager.createPlayer(is, "audio/mpeg");
			
			is = getClass().getResourceAsStream("/sounds/seagull2.mp3");
			seagull2 = Manager.createPlayer(is, "audio/mpeg");
			
			is = getClass().getResourceAsStream("/sounds/horn.mp3");
			horn = Manager.createPlayer(is, "audio/mpeg");
			
//			is = getClass().getResourceAsStream("/sounds/splash.mp3");
//			splash = Manager.createPlayer(is, "audio/mpeg");
			
			is = getClass().getResourceAsStream("/sounds/flash.mp3");
			flash = Manager.createPlayer(is, "audio/mpeg");
		}
		catch (IllegalArgumentException e) {
			System.out.println("Sounds konnten nicht geladen werden.");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("Sounds konnten nicht geladen werden.");
			e.printStackTrace();
		} catch (MediaException e) {
			System.out.println("Sounds konnten nicht geladen werden.");
			e.printStackTrace();
		}
		
		try {
			bgLoop.realize();
			seagull1.realize();
			seagull2.realize();
			horn.realize();
//			splash.realize();
			flash.realize();
		} catch (MediaException e) {
			System.out.println("Sounds konnten nicht gerealized werden.");
			e.printStackTrace();
		}
		
		try {
			bgLoop.prefetch();
			seagull1.prefetch();
			seagull2.prefetch();
			horn.prefetch();
//			splash.prefetch();
			flash.prefetch();
		} catch (MediaException e) {
			System.out.println("Sounds konnten nicht geprefetched werden.");
			e.printStackTrace();
		}
		
		bgLoop.setLoopCount(-1);		//TODO da is immer a kurze pause
		
		((VolumeControl)bgLoop.getControl("VolumeControl")).setLevel(40);
	}
	
	/**
	 * Start the background sound loop.
	 */
	public void startSoundLoop() {
		try {
			bgLoop.start();
		} catch (MediaException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Stop the background sound loop.
	 */
	public void stopSoundLoop() {
		try {
			bgLoop.start();
		} catch (MediaException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Gets the mute status as string for the display-text.
	 *
	 * @return the mute status string
	 */
	public String getMuteStatusString() {
		if(this.muted)
			return "OFF";
		else
			return "ON";
	}
}
